
#include "shading.fx"
#include "samplers.fx"
#include "fog.fx"

struct VS_IN
{
	float3 position : POSITION;
	float3 normal	: NORMAL;
	float3 tangent : TANGENT;
	float2 tex		: TEX_COORDS;
};


struct VS_OUT
{
	float4 position : SV_POSITION;
	float4 ws_pos	: WS_POSITION;
	float3 normal	: NORMAL;
	float2 tex		: TEX_COORDS;
};




float4x4 m_World;
float4x4 m_WorldViewProj;

TextureCube tex_reflections;

VS_OUT VS(VS_IN vin)
{
	VS_OUT vout;

	vout.position = mul(float4(vin.position, 1.0f), m_WorldViewProj);
	vout.ws_pos = mul(float4(vin.position, 1.0f), m_World);
	vout.normal = mul(float4(vin.normal, 0.0f), m_World).xyz;
	vout.tex =	  vin.tex;
	return vout;
}


float4 PS(VS_OUT pin) : SV_TARGET
{
	float4 color = float4(shade(pin.ws_pos.xyz, normalize(pin.normal), 0), 1.0f);

	if (mat_params.vIsTextured.x)
	{
		float4 tex_diff = tex_diffuse.Sample(s_linear, pin.tex);
		color *= tex_diff;
	}
	// set alpha in w
	color.w = mat_params.diffuse.w;
	
	// compute reflect vector
	float3 R = reflect(pin.ws_pos.xyz - pEye, normalize(pin.normal));
	float4 refl = tex_reflections.Sample(s_linear, R);

	color.xyz = 0.2f * color.xyz + 0.8f * refl.xyz;
	color = computeFog(color, pin.ws_pos.xyz, pin.ws_pos.y, 3.0f, pEye);

	return color;
}


RasterizerState rs_cullBack
{
	CullMode = Back;
};


BlendState bs_transparent
{
	AlphaToCoverageEnable = false;
	BlendEnable[0] = true;
	

	SrcBlend[0] = SRC_ALPHA;
	DestBlend[0] = INV_SRC_ALPHA;
	BlendOp[0] = ADD;

	SrcBlendAlpha[0] = ONE;
	DestBlendAlpha[0] = ZERO;
	BlendOpAlpha[0] = ADD; 
};

technique10 Bottle 
{
    pass P0 
	{
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
		SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
		
		SetRasterizerState(rs_cullBack);
		SetBlendState(bs_transparent, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xffffffff);

	}
}



//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////


struct EM_VS_OUT
{
	float4 ws_pos	: WS_POSITION;
	float3 normal	: NORMAL;
	float2 tex		: TEX_COORDS;
};


EM_VS_OUT VS_Reflection(VS_IN vin)
{
	EM_VS_OUT vout;

	vout.ws_pos = mul(float4(vin.position, 1.0f),	m_World);
	vout.normal = mul(float4(vin.normal, 0.0f),		m_World).xyz;
	vout.tex =	  vin.tex;

	return vout;
}

struct EM_GS_OUT
{
	float4 position : SV_POSITION;
	float4 ws_pos	: WS_POSITION;
	float3 normal	: NORMAL;
	float2 tex		: TEX_COORDS;
	uint rtv_index	: SV_RenderTargetArrayIndex;
};

float4x4 m_View[6];
float4x4 m_Proj;

[maxvertexcount(18)]
void GS(triangle EM_VS_OUT gin[3], inout TriangleStream<EM_GS_OUT> gsout)
{
	
	for(int i=0; i<6; i++)
	{
        EM_GS_OUT gout;
        gout.rtv_index = i;

        for(int j=0; j<3; j++)
        {
            gout.position = mul(gin[j].ws_pos, m_View[i]);
			gout.position = mul(gout.position, m_Proj);
            gout.ws_pos = gin[j].ws_pos;
			gout.normal = gin[j].normal;
			gout.tex    = gin[j].tex;
            gsout.Append(gout);
        }
        gsout.RestartStrip();
    }
}


float4 PS_Reflection(EM_GS_OUT pin) : SV_TARGET
{
	
	float4 color = float4(shade(pin.ws_pos.xyz, normalize(pin.normal), 0), 1.0f)
					+ float4(0.1f, 0.1f, 0.1f, 0.0f);
	
	float4 ambient = float4(0.1f, 0.1f, 0.1f, 0.0f);
	
	if (mat_params.vIsTextured.x)
	{
		float4 tex_diff = tex_diffuse.Sample(s_linear, pin.tex);
		ambient *= tex_diff;
		color *= tex_diff;
	}

	color += ambient;

	color = float4(color.xyz, mat_params.diffuse.w);

	return color;
}


technique10 Reflection 
{
    pass P0 
	{
        SetVertexShader( CompileShader( vs_4_0, VS_Reflection() ) );
		SetGeometryShader( CompileShader ( gs_4_0, GS() ));
        SetPixelShader( CompileShader( ps_4_0, PS_Reflection() ) );

		SetRasterizerState(rs_cullBack);
	}
}